import stackless
import time
import util
from copy import copy

class Service:
    _services = []
    _actionCount = 0

    def __init__(self):
        self.tasklets = []
        
        self._services.append(self)
        self.stopped = False

        self.tasklet = stackless.tasklet(self.doRun)
        self.tasklets.append(self.tasklet)
        
    def __call__(self, **args):
        self.tasklet(**args)
        
    def doRun(self, **args):
        try:
            self.run(**args)
        finally:
            self.stop()

    def stop(self):
        if not self.stopped:
            self.stopped = True
            
            def doStop():
                for tasklet in self.tasklets:
                    tasklet.kill()
                self.kill()
                self._services.remove(self)
                
                #if self._actionCount <= 0:
                    #self.log("actionCount shutdown")
                    #self.killAll()
                    
            stackless.tasklet(doStop)()
        
    @classmethod
    def schedule(self):
        stackless.schedule()

    @classmethod
    def wait(self, cond = None, proc = None, retry = None, retryTime = 1):
        if retry:
            retryStart = time.time()
        while not cond or cond():
            self.schedule()
            if proc:
                proc()
            if retry and time.time() - retryStart > retryTime:
                retryStart = time.time()
                retry()

    @classmethod
    def sleep(self, sleepTime):
        start = time.time()
        self.wait(lambda: time.time() - start < sleepTime)

    @classmethod
    def enumerateTime(self, minTime = None, maxTime = None):
        start = time.time()
        tickStart = start
        if minTime:
            nextTick = start + minTime
        while not maxTime or time.time() - start < maxTime:
            self.schedule()
            if minTime:
                self.wait(lambda: time.time() < nextTick)
                nextTick += minTime
            currentTime = time.time()
            dtime = currentTime - tickStart
            tickStart = currentTime
            yield currentTime - start, dtime
            
        #tickStart = start = time.time()
        #while not maxTime or time.time() - start < maxTime:
            #if minTime:
                #self.sleep(minTime)
            #else:
                #self.schedule()
            #currentTime = time.time()
            #dtime = currentTime - tickStart
            #tickStart = currentTime
            #yield currentTime - start, dtime

    def run(self, **args):
        self.wait()

    def kill(self):
        pass

    @staticmethod
    def killAll():
        for service in Service._services:
            service.stop()
        Service.wait(lambda: Service._services, Service.schedule)
        #raise SystemExit

    @staticmethod
    def runAll():
        stackless.run()
        
    def log(self, *v):
        print "%s: %s" % (self.__class__.__name__, ' '.join(map(str,v)))
